package com.cgy.utils.tokenizer.factory;

import com.cgy.utils.tokenizer.dictionary.Dictionary;
import com.cgy.utils.tokenizer.segment.Serpentine;
import com.google.common.base.Preconditions;
import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.dictionary.CustomDictionary;
import com.hankcs.hanlp.seg.Dijkstra.DijkstraSegment;
import com.hankcs.hanlp.seg.NShort.NShortSegment;
import com.hankcs.hanlp.seg.Segment;
import com.hankcs.hanlp.seg.common.Term;
import com.hankcs.hanlp.tokenizer.IndexTokenizer;

import java.util.List;
import java.util.Map;

/**
 * 
 * @author Administrator
 *
 */
public class SegmentFactory implements ISegmentFactory {
	// 分词器
	private Segment segment;
	private String[] speeches;

	private static final String[] NAME_SPEECHES = new String[] {"nr", "nrj", "nrf", "nr1", "nr2"};
	private static final String[] PLACE_SPEECHES = new String[] {"ns", "nsf"};
	private String[] nptSpeeches;

	public SegmentFactory() {
		this.segment = HanLP.newSegment();
	}

	public SegmentFactory(Segment segment) {
		this.segment = segment;
	}

	@Override
	public ISegmentFactory newSegment() {
		return new SegmentFactory(HanLP.newSegment());
	}

	@Override
	public ISegmentFactory newNShortSegment() {
		return new SegmentFactory(new NShortSegment());
	}

	@Override
	public ISegmentFactory newDShortSegment() {
		return new SegmentFactory(new DijkstraSegment());
	}

	/**
	 * 开启人名识别
	 * 
	 * @param enable
	 * @return
	 */
	public SegmentFactory enableNameRecognize(boolean enable) {
		segment.enableNameRecognize(enable);
		return this;
	}

	/**
	 * 音译人名识别
	 * 
	 * @param enable
	 * @return
	 */
	public SegmentFactory enableTranslatedNameRecognize(boolean enable) {
		segment.enableTranslatedNameRecognize(enable);
		return this;
	}

	/**
	 * 开启地名识别
	 * 
	 * @param enable
	 * @return
	 */
	public SegmentFactory enablePlaceRecognize(boolean enable) {
		segment.enablePlaceRecognize(enable);
		return this;
	}
	/**
	 * 开启词性标注
	 *
	 * @param enable
	 * @return
	 */
	public SegmentFactory enablePartOfSpeechTagging(boolean enable) {
		segment.enablePartOfSpeechTagging(enable);
		return this;
	}
	/**
	 * 是否启用所有的命名实体识别
	 *
	 * @param enable
	 * @return
	 */
	public SegmentFactory enableAllNamedEntityRecognize(boolean enable) {
		segment.enableAllNamedEntityRecognize(enable);
		return this;
	}
	/**
	 * 是否尽可能强制使用用户词典（使用户词典的优先级尽可能高）<br>
	 *     警告：具体实现由各子类决定，可能会破坏分词器的统计特性（例如，如果用户词典
	 *     含有“和服”，则“商品和服务”的分词结果可能会被用户词典的高优先级影响）。
	 * @param enable
	 * @return 分词器本身
	 *
	 * @since 1.3.5
	 */
	public SegmentFactory enableCustomDictionaryForcing(boolean enable) {
		segment.enableCustomDictionaryForcing(enable);
		return this;
	}

	/**
	 * 自定义字典识别
	 * 
	 * @param dictionary
	 * @return
	 */
	public SegmentFactory enableCustomDictionary(Dictionary dictionary) {
		Preconditions.checkArgument(null != dictionary);
		if (!dictionary.isEmpty()) {
			segment.enableCustomDictionary(true);
			List<String> list = dictionary.toList();
			if (!list.isEmpty()) {
				for (String word : list) {
					CustomDictionary.add(word);
				}
			}

			Map<String, String> map = dictionary.toMap();

			if (!map.isEmpty()) {
				for (Map.Entry<String, String> entry : map.entrySet()) {
					CustomDictionary.insert(entry.getKey(), entry.getValue());
				}
			}
		}

		return this;
	}

	/**
	 * 机构识别
	 * 
	 * @param enable
	 * @return
	 */
	public SegmentFactory enableOrganizationRecognize(boolean enable) {
		segment.enableOrganizationRecognize(enable);
		return this;
	}
	/**
	 * 识别
	 * 
	 * @param enable
	 * @return
	 */
	public SegmentFactory enableJapaneseNameRecognize(boolean enable) {
		segment.enableJapaneseNameRecognize(enable);
		return this;
	}
	 /**
     * 开启多线程
     * @param threadNumber 线程数量
     * @return
     */
	public SegmentFactory enableMultithreading(int threadNumber) {
		segment.enableMultithreading(threadNumber);
		return this;
	}
	 /**
     * 结果不保留词性
     * @param speeches
     * @return
     */
	public SegmentFactory keepNptSpeech(final String... speeches) {
		this.nptSpeeches = speeches;
		return this;
	}
	 /**
     * 结果不保留词性
     * @param speeches
     * @return
     */
	public SegmentFactory keepNptWSpeech(final String... speeches) {
		this.nptSpeeches = new String[] {"w"};
		return this;
	}
	 /**
     * 结果保留词性
     * @param speeches
     * @return
     */
	public SegmentFactory keepSpeech(final String... speeches) {
		this.speeches = speeches;
		return this;
	}
	 /**
     * 结果保留词性
     * @return
     */
	public SegmentFactory keepNameSpeech() {
		this.speeches = NAME_SPEECHES;
		return this;
	}
	 /**
     * 结果保留词性
     * @return
     */
	public SegmentFactory keepPlaceSpeech() {
		this.speeches = PLACE_SPEECHES;
		return this;
	}
	/**
	 * 开启多线程
	 * @param enable
	 * @return
	 */
	public SegmentFactory enableMultithreading(boolean enable) {
		segment.enableMultithreading(enable);
		return this;
	}
	  /**
     * 是否启用数词和数量词识别<br>
     *     即[二, 十, 一] => [二十一]，[十, 九, 元] => [十九元]
     * @param enable
     * @return
     */
	public SegmentFactory enableNumberQuantifierRecognize(boolean enable) {
		segment.enableNumberQuantifierRecognize(enable);
		return this;
	}


	/**
	 * 分词
	 * 
	 * @param words
	 * @return
	 */
	@Override
	public Serpentine seg(final String... words) {
		Preconditions.checkArgument(words.length > 0);
		List<Term> seg = segment.seg(newWords(words));
		return translate(seg);
	}

	/**
	 * 分词
	 * 
	 * @param words
	 * @return
	 */
	@Override
	public Serpentine keyword(int size, final String... words) {
		Serpentine segmenting = new Serpentine();
		List<String> keywordList = HanLP.extractKeyword(newWords(words), size);
		segmenting.setWords(keywordList);
		return segmenting;
	}

	@Override
	public Serpentine index(String... words) {
		Preconditions.checkArgument(words.length > 0);
		List<Term> termList = IndexTokenizer.segment(newWords(words));
		return translate(termList);
	}

	/**
	 * 
	 * @return
	 */
	private String newWords(final String... words) {
		Preconditions.checkArgument(words.length > 0);

		StringBuilder stringBuilder = new StringBuilder();
		for (String word : words) {
			stringBuilder.append("\r\n").append(word);
		}
		String newWords = stringBuilder.substring(1).toString();
		return newWords;
	}

	/**
	 * 结果转化
	 * @param terms
	 * @return
	 */
	private Serpentine translate(List<Term> terms) {
		Serpentine segmenting = new Serpentine();
		for (Term term : terms) {
			if(null != speeches || null != nptSpeeches) {
				String s = term.nature.toString();
				if(indexOf(s)) {
					segmenting.append(term.word);
					segmenting.put(term.word, term.nature);
				}
			} else {
				segmenting.append(term.word);
				segmenting.put(term.word, term.nature);
			}
		}
		return segmenting;
	}

	/**
	 *
	 * @param key
	 * @return
	 */
	private boolean indexOf(String key) {
		return indexOf(speeches, key) && !indexOf(nptSpeeches, key);
	}
	/**
	 *
	 * @param key
	 * @return
	 */
	private boolean indexOf(String[] speeches, String key) {
		if(null == speeches || speeches.length == 0) {
			return false;
		}
		for (String speech : speeches) {
			if(speech.equals(key)) {
				return true;
			}
		}
		return false;
	}

	@Override
	public Serpentine nShortSegment(String... words) {
		return null;
	}

	@Override
	public Serpentine DijkstraSegment(String... words) {
		return null;
	}
}
